package com.keter.framework.web.component.sequence;

import com.alibaba.fastjson.JSONObject;
import com.keter.framework.web.component.sequence.core.Sequence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;
import java.util.Date;

public class Decoder {

    private static final Logger logger = LoggerFactory.getLogger(Decoder.class);

    //与生成器起始日期保持一致
    private static long twepoch = Sequence.START_TIME;

    private long datacenterIdBits = 2L;
    private long workerIdBits = 8L;

    private static final long sequenceBits = 12L;

    private long workerIdShift = sequenceBits;
    private long dataCenterIdShift = sequenceBits + workerIdBits;
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    public Decoder(){
        this.datacenterIdBits = 2L;
        this.workerIdBits = 8L;
    }

    public Decoder(long datacenterIdBits, long workerIdBits, long start){
        this.datacenterIdBits = datacenterIdBits;
        this.workerIdBits = workerIdBits;
        Decoder.twepoch = start;
    }

    public JSONObject decode(long id) {
        String sonwFlakeId = Long.toBinaryString(id);
        int len = sonwFlakeId.length();
        JSONObject jsonObject = new JSONObject();
        int sequenceStart = (int) (len < workerIdShift ? 0 : len - workerIdShift);
        int workerStart = (int) (len < dataCenterIdShift ? 0 : len - dataCenterIdShift);
        int timeStart = (int) (len < timestampLeftShift ? 0 : len - timestampLeftShift);
        String sequence = sonwFlakeId.substring(sequenceStart, len);
        String workerId = sequenceStart == 0 ? "0" : sonwFlakeId.substring(workerStart, sequenceStart);
        String dataCenterId = workerStart == 0 ? "0" : sonwFlakeId.substring(timeStart, workerStart);
        String time = timeStart == 0 ? "0" : sonwFlakeId.substring(0, timeStart);
        int sequenceInt = Integer.valueOf(sequence, 2);
        jsonObject.put("sequence", sequenceInt);
        int workerIdInt = Integer.valueOf(workerId, 2);
        jsonObject.put("workerId", workerIdInt);
        int dataCenterIdInt = Integer.valueOf(dataCenterId, 2);
        jsonObject.put("dataCenter", dataCenterIdInt);
        long diffTime = Long.parseLong(time, 2);
        long timeLong = diffTime + twepoch;
        Date date = fromatTime(timeLong);
        jsonObject.put("date", date);
        return jsonObject;
    }

    public static Date getDate(long id) {
        Decoder sonwFlakeId = new Decoder();
        JSONObject jsonObject = sonwFlakeId.decode(id);
        return (Date)jsonObject.get("date");
    }

    private static Date fromatTime(long date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(date);
        return calendar.getTime();
    }

    public static void main(String[] args) {
        Sequence sequence = new Sequence(1);
        long sid = sequence.nextId();
        Decoder decoder = new Decoder();
        logger.info("sid info:{}",decoder.decode(sid));
        logger.info("sid date:{}", Decoder.getDate(sid));
    }
}